home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Tools / Utility / DisplayNameRegistry 950412 / Src / AppleEventCore.c next >
Encoding:
C/C++ Source or Header  |  1997-02-27  |  24.7 KB  |  1,120 lines  |  [TEXT/MPCC]

  1. /*                                    AppleEventCore.c                            */
  2. /*
  3.  * AppleEventCore.c
  4.  * Copyright © 1988-94 Apple Computer Inc. All rights reserved.
  5.  * Note: a lot of these functions are not (yet) used.
  6.  */
  7. #include "AppleEventCore.h"
  8. #include <AERegistry.h>
  9. #include <AppleTalk.h>
  10. #include <Gestalt.h>
  11. #include <Dialogs.h>
  12. #include <Errors.h>
  13. #include <Script.h>
  14. #include <TextUtils.h>
  15.  
  16. #ifndef FALSE
  17. #define FALSE        0
  18. #define TRUE        1
  19. #endif
  20.  
  21. AECoreGlobals                    gAECoreGlobals;
  22. #define GLOBAL                    (gAECoreGlobals)
  23. Boolean                            gHasAppleEvents;
  24. static AEOpenAppHandlerFunc        gAEOpenAppHandlerFunc;
  25. static AEDocumentHandlerFunc    gAEOpenDocHandlerFunc;
  26. static AEDocumentHandlerFunc    gAEPrintDocHandlerFunc;
  27. static AEQuitAppHandlerFunc        gAEQuitAppHandlerFunc;
  28. static AEDoScriptHandlerFunc    gAEDoScriptHandlerFunc;
  29. static AEUnknownHandlerMsgFunc    gAEUnknownHandlerMsgFunc;
  30.  
  31. static pascal OSErr            AEOpenApplication(
  32.         const AppleEvent        *theEvent,
  33.         AppleEvent                *theReply,
  34.         long                    refCon
  35.     );
  36. static pascal OSErr            AEOpenDocument(
  37.         const AppleEvent        *theEvent,
  38.         AppleEvent                *theReply,
  39.         long                    refCon
  40.     );
  41. static pascal OSErr            AEPrintDocument(
  42.         const AppleEvent        *theEvent,
  43.         AppleEvent                *theReply,
  44.         long                    refCon
  45.     );
  46. static pascal OSErr            AEQuit(
  47.         const AppleEvent        *theEvent,
  48.         AppleEvent                *theReply,
  49.         long                    refCon
  50.     );
  51. static OSErr                AEOpenOrPrint(
  52.         const AppleEvent        *theEvent,
  53.         AppleEvent                *theReply,
  54.         long                    refCon,
  55.         AEDocumentHandlerFunc    aeDocumentHandlerFunc
  56.     );
  57. static pascal OSErr            AEUnknownHandler(
  58.         const AppleEvent        *theEvent,
  59.         AppleEvent                *theReply,
  60.         long                    refCon
  61.     );
  62. static pascal OSErr            AEDoScript(
  63.         const AppleEvent        *theEvent,
  64.         AppleEvent                *theReply,
  65.         long                    refCon
  66.     );
  67. static void                    AEGetMyZone(
  68.         Str32                    zoneName
  69.     );
  70.  
  71. /*
  72.  * Define a table used to install event handlers.
  73.  */
  74. const static AEHandlerDefRec    gAEHandlerDefs[] = {
  75.     { kCoreEventClass,    kAEStartRecording,            AEIgnore                    },
  76.     { kCoreEventClass,    kAEStopRecording,            AEIgnore                    },
  77.     { kCoreEventClass,    kAENotifyRecording,            AEIgnore                    },
  78.     { kCoreEventClass,    kAENotifyStopRecording,        AEIgnore                    },
  79.     { kCoreEventClass,    kAENotifyStartRecording,    AEIgnore                    },
  80.     { kCoreEventClass,    kAEOpenApplication,            AEOpenApplication            },
  81.     { kCoreEventClass,    kAEOpenDocuments,            AEOpenDocument                },
  82.     { kCoreEventClass,    kAEPrintDocuments,            AEPrintDocument                },
  83.     { kCoreEventClass,    kAEQuitApplication,         AEQuit                        },
  84.     { 0,                0,                            NULL                        }
  85. };
  86.  
  87. #define UNUSED(what)    (what)
  88.  
  89. static void                    ClearMemory(
  90.         register void            *ptr,
  91.         register long            size
  92.     );
  93. #define CLEAR(rec)    (ClearMemory(&rec, sizeof rec))
  94. static void                    pstrcpy(
  95.         StringPtr                dst,
  96.         ConstStr255Param        src
  97.     );
  98. static void                    pstrcat(
  99.         StringPtr                dst,
  100.         ConstStr255Param        src
  101.     );
  102.  
  103. pascal OSErr
  104. InitializeAppleEvents(
  105.         AEOpenAppHandlerFunc    aeOpenAppHandlerFunc,
  106.         AEDocumentHandlerFunc    aeOpenDocHandlerFunc,
  107.         AEDocumentHandlerFunc    aePrintDocHandlerFunc,
  108.         AEQuitAppHandlerFunc    aeQuitAppHandlerFunc,
  109.         AEDoScriptHandlerFunc    aeDoScriptHandlerFunc,
  110.         AEUnknownHandlerMsgFunc    aeUnknownHandlerMsgFunc,
  111.         long                    refCon
  112.     )
  113. {
  114.         long                    response;
  115.         OSErr                    status;
  116.  
  117.         status = Gestalt(gestaltAppleEventsAttr, &response);
  118.         gHasAppleEvents = (
  119.                     status == noErr
  120.                     && (response & (1L << gestaltAppleEventsPresent) != 0)
  121.                 );
  122.         status = (gHasAppleEvents == FALSE) ? gestaltUndefSelectorErr : noErr;
  123.         if (status == noErr) {
  124.             gAEOpenAppHandlerFunc = aeOpenAppHandlerFunc;
  125.             gAEOpenDocHandlerFunc = aeOpenDocHandlerFunc;
  126.             gAEPrintDocHandlerFunc = aePrintDocHandlerFunc;
  127.             gAEQuitAppHandlerFunc = aeQuitAppHandlerFunc;
  128.             gAEDoScriptHandlerFunc = aeDoScriptHandlerFunc;
  129.             gAEUnknownHandlerMsgFunc = aeUnknownHandlerMsgFunc;
  130.             status = AEInstallEventHandlers(
  131.                         (AEHandlerDefPtr) gAEHandlerDefs, refCon);
  132.         }
  133.         if (status == noErr && aeDoScriptHandlerFunc != NULL) {
  134.             status = AEInstallEventHandler(
  135.                         kAEMiscStandards,
  136.                         kAEDoScript,
  137.                         NewAEEventHandlerProc(AEDoScript),
  138.                         0,                        /* No refCon                */
  139.                         FALSE                    /* Not system event            */
  140.             );
  141.         }
  142.         if (status == noErr && aeUnknownHandlerMsgFunc != NULL) {
  143.             status = AEInstallEventHandler(
  144.                         typeWildCard,
  145.                         typeWildCard,
  146.                         NewAEEventHandlerProc(AEUnknownHandler),
  147.                         0,                        /* No refCon                */
  148.                         FALSE                    /* Not system event            */
  149.             );
  150.         }
  151.         return (status);
  152. }
  153.  
  154. /*
  155.  * Initialize for apple events: and setup the handler callbacks so we process
  156.  * events. Fail if a handler can't be installed. The caller should check
  157.  * gHasAppleEvents to see if they are actually present.
  158.  */
  159. pascal OSErr
  160. AEInstallEventHandlers(
  161.         AEHandlerDefPtr            aeHandlerDefPtr,
  162.         long                    refCon
  163.     )
  164. {
  165.         OSErr                    status;
  166.  
  167.         status = noErr;
  168.         if (aeHandlerDefPtr != NULL) {
  169.             while (status == noErr && aeHandlerDefPtr->procPtr != NULL) {
  170.                 status = AEInstallEventHandler(
  171.                             aeHandlerDefPtr->eventClass,
  172.                             aeHandlerDefPtr->eventID,
  173.                             NewAEEventHandlerProc(aeHandlerDefPtr->procPtr),
  174.                             refCon,
  175.                             FALSE                    /* Not system event            */
  176.                 );
  177.                 ++aeHandlerDefPtr;
  178.             }
  179.         }
  180.         return (status);
  181. }
  182.  
  183. /*
  184.  * Initialize for apple events: and setup the coercion callbacks so we process
  185.  * events. Fail if a handler can't be installed. The caller should check
  186.  * gHasAppleEvents to see if they are actually present.
  187.  */
  188. pascal OSErr
  189. AEInstallCoercionHandlers(
  190.         AECoercionDefPtr        aeCoercionDefPtr,
  191.         long                    refCon
  192.     )
  193. {
  194.         OSErr                    status;
  195.  
  196.         status = noErr;
  197.         if (aeCoercionDefPtr != NULL) {
  198.             while (aeCoercionDefPtr->procPtr != NULL) {
  199.                 status = AEInstallCoercionHandler(
  200.                             aeCoercionDefPtr->fromType,
  201.                             aeCoercionDefPtr->toType,
  202.                             NewAECoerceDescProc(aeCoercionDefPtr->procPtr),
  203.                             refCon,
  204.                             FALSE,                    /* Pass data                */
  205.                             FALSE                    /* Not system handler        */
  206.                         );
  207.                 ++aeCoercionDefPtr;
  208.             }
  209.         }
  210.         return (status);
  211. }
  212.  
  213. /*
  214.  * Open (initial double-click) the application. The handler is optional.
  215.  */
  216. static pascal OSErr
  217. AEOpenApplication(
  218.         const AppleEvent        *theEvent,
  219.         AppleEvent                *theReply,
  220.         long                    refCon
  221.     )
  222. {
  223.         OSErr                    status;
  224.         
  225.         status = AEHandlerSetup(theEvent, theReply, refCon);
  226.         if (status == noErr)
  227.             status = AEGotRequiredParams(theEvent);
  228.         if (status == noErr && gAEOpenAppHandlerFunc != NULL)
  229.             status = (*gAEOpenAppHandlerFunc)(refCon);    /* Application specific    */
  230.         GLOBAL.currentEventIsAppleEvent = FALSE;
  231.         return (status);        
  232. }
  233.  
  234.  
  235. /*
  236.  * Open a document. This can be called at application setup, but it can also
  237.  * be called by dropping a document on the application icon.
  238.  */
  239. static pascal OSErr
  240. AEOpenDocument(
  241.         const AppleEvent        *theEvent,
  242.         AppleEvent                *theReply,
  243.         long                    refCon
  244.     )
  245. {
  246.         OSErr                    status;
  247.         
  248.         status = AEOpenOrPrint(theEvent, theReply, refCon, gAEOpenDocHandlerFunc);
  249.         return (status);
  250. }
  251.  
  252. /*
  253.  * Print a document. This can be called at application setup, but it can also
  254.  * be called by dropping a document on the application icon.
  255.  */
  256. static pascal OSErr
  257. AEPrintDocument(
  258.         const AppleEvent        *theEvent,
  259.         AppleEvent                *theReply,
  260.         long                    refCon
  261.     )
  262. {
  263.         OSErr                    status;
  264.  
  265.         status = AEOpenOrPrint(theEvent, theReply, refCon, gAEPrintDocHandlerFunc);
  266.         return (status);
  267. }
  268.  
  269. /*
  270.  * This is the common handler for AppleEvent open document and print document.
  271.  * The actual work is done by application-specific code.
  272.  */
  273. static OSErr
  274. AEOpenOrPrint(
  275.         const AppleEvent        *theEvent,
  276.         AppleEvent                *theReply,
  277.         long                    refCon,
  278.         AEDocumentHandlerFunc    aeDocumentHandlerFunc
  279.     )
  280. {
  281.         OSErr                    status;
  282.         AEDesc                    theDesc;
  283.         long                    numberOfFiles;
  284.         long                    iFile;
  285.         AEKeyword                ignoredKeyWord;
  286.         DescType                ignoredType;
  287.         Size                    ignoredSize;
  288.         FSSpec                    theFSS;
  289.         
  290.         theDesc.dataHandle = NULL;;
  291.         status = (aeDocumentHandlerFunc == NULL) ? errAEEventNotHandled : noErr;
  292.         if (status == noErr)
  293.             status = AEHandlerSetup(theEvent, theReply, refCon);
  294.         if (status == noErr)
  295.             status = AEGetParamDesc(theEvent, keyDirectObject, typeAEList, &theDesc);
  296.         if (status == noErr)
  297.             status = AEGotRequiredParams(theEvent);
  298.         if (status == noErr)
  299.             status = AECountItems(&theDesc, &numberOfFiles);
  300.         for (iFile = 1; status == noErr && iFile <= numberOfFiles; iFile++) {
  301.             status = AEGetNthPtr(
  302.                         &theDesc,
  303.                         iFile,
  304.                         typeFSS,
  305.                         &ignoredKeyWord,
  306.                         &ignoredType,
  307.                         (Ptr) &theFSS,
  308.                         sizeof theFSS,
  309.                         &ignoredSize
  310.                     );
  311.             if (status == noErr) {
  312.                 /*
  313.                  * Note that an error from the handler will terminate all files.
  314.                  */
  315.                 status = (*aeDocumentHandlerFunc)(&theFSS, refCon);
  316.             }
  317.         }
  318.         (void) AEDisposeDesc(&theDesc);
  319.         GLOBAL.currentEventIsAppleEvent = FALSE;
  320.         return (status);
  321. }
  322.  
  323. static pascal OSErr
  324. AEQuit(
  325.         const AppleEvent        *theEvent,
  326.         AppleEvent                *theReply,
  327.         long                    refCon
  328.     )
  329. {
  330.         OSErr                    status;
  331.  
  332.         status = (gAEQuitAppHandlerFunc == NULL) ? errAEEventNotHandled : noErr;
  333.         if (status == noErr)
  334.             status = AEHandlerSetup(theEvent, theReply, refCon);
  335.         if (status == noErr)
  336.             status = AEGotRequiredParams(theEvent);
  337.         status = (*gAEQuitAppHandlerFunc)(refCon);
  338.         GLOBAL.currentEventIsAppleEvent = FALSE;
  339.         return (status);        
  340. }
  341.                 
  342. /*
  343.  * This handler is called for "scripting on/off" events. They are ignored.
  344.  */
  345. pascal OSErr
  346. AEIgnore(
  347.         const AppleEvent        *theEvent,
  348.         AppleEvent                *theReply,
  349.         long                    refCon
  350.     )
  351. {
  352.         UNUSED(theEvent);
  353.         UNUSED(theReply);
  354.         UNUSED(refCon);
  355.         GLOBAL.currentEventIsAppleEvent = FALSE;
  356.         return (noErr);
  357. }
  358.  
  359. /*
  360.  * Unknown events go here. If the application provides an alert, call it.
  361.  * The initializer has provided a handler functions.
  362.  */
  363. static pascal OSErr
  364. AEUnknownHandler(
  365.         const AppleEvent        *theEvent,
  366.         AppleEvent                *theReply,
  367.         long                    refCon
  368.     )
  369. {
  370.         OSErr                    status;
  371.         OSType                    eventClass;
  372.         OSType                    eventID;
  373.         OSType                    typeCode;
  374.         Size                    actualSize;
  375.         Str255                    work;
  376.         
  377.         status = AEHandlerSetup(theEvent, theReply, refCon);
  378.         if (status == noErr) {
  379.             status = AEGetAttributePtr(
  380.                 theEvent,
  381.                 keyEventClassAttr,
  382.                 typeType,
  383.                 &typeCode,
  384.                 (Ptr) &eventClass,
  385.                 sizeof(eventClass),
  386.                 &actualSize
  387.             );
  388.         }
  389.         if (status == noErr) {
  390.             AEGetAttributePtr(
  391.                 theEvent,
  392.                 keyEventIDAttr,
  393.                 typeType,
  394.                 &typeCode,
  395.                 (Ptr) &eventID,
  396.                 sizeof(eventID),
  397.                 &actualSize
  398.             );
  399.         }
  400.         if (status == noErr) {
  401.             pstrcpy(work, "\pUnknown AppleEvent. Class ");
  402.             BlockMoveData(&eventClass, &work[work[0] + 1], sizeof (OSType));
  403.             work[0] += sizeof (OSType);
  404.             pstrcat(work, "\p, ID ");
  405.             BlockMoveData(&eventID, &work[work[0] + 1], sizeof (OSType));
  406.             work[0] += sizeof (OSType);
  407.             (*gAEUnknownHandlerMsgFunc)(work);
  408.         }
  409.         GLOBAL.currentEventIsAppleEvent = FALSE;
  410.         return (errAEHandlerNotFound);        
  411. }
  412.  
  413. /*
  414.  * This processes the Do Script event. The application provided a handler.
  415.  */
  416. static pascal OSErr
  417. AEDoScript(
  418.         const AppleEvent        *theEvent,
  419.         AppleEvent                *theReply,
  420.         long                    refCon
  421.     )
  422. {
  423.         CharsHandle                scriptHandle;
  424.         OSErr                    status;
  425.         
  426.         scriptHandle = NULL;
  427.         status = AEHandlerSetup(theEvent, theReply, refCon);
  428.         if (status == noErr)
  429.             status = AEGetChars(theEvent, keyDirectObject, &scriptHandle);
  430.         if (status == noErr)
  431.             status = AEGotRequiredParams(theEvent);
  432.         if (status == noErr) {
  433.             /*
  434.              * Make sure there's a null trailer.
  435.              */
  436.             status = PtrAndHand("", (Handle) scriptHandle, 1);
  437.         }
  438.         if (status == noErr) {
  439.             MoveHHi((Handle) scriptHandle);
  440.             HLock((Handle) scriptHandle);
  441.             status = (*gAEDoScriptHandlerFunc)(
  442.                         (Ptr) *scriptHandle,
  443.                         GetHandleSize((Handle) scriptHandle),
  444.                         theReply,
  445.                         refCon
  446.                 );
  447.         }
  448.         if (scriptHandle != NULL) {
  449.             DisposeHandle((Handle) scriptHandle);
  450.             scriptHandle = NULL;
  451.         }
  452.         GLOBAL.currentEventIsAppleEvent = FALSE;
  453.         return (status);
  454. }
  455.  
  456. /*
  457.  * Utilities
  458.  */
  459. /*
  460.  * Build an AppleEvent descriptor for a target address. The addressMode parameter
  461.  * chooses the target:
  462.  *    kSelfCurrentProcess    direct calls to this application (for scripting)
  463.  *    kSelfUsingPSN        event-loop based calls to this application (script debug)
  464.  *    kOtherApplication    dialog-based calls to an external application.
  465.  */
  466. pascal OSErr
  467. AEMakeTargetAddress(
  468.         AETargetAddressType        aeTargetAddressType,
  469.         AEDesc                    *theAddress,
  470.         StringPtr                targetName
  471.     )
  472. {
  473.         OSErr                    status;
  474.         ProcessSerialNumber        myPSN;
  475.         StringPtr                theTarget;
  476.         
  477.         theTarget = "\p";            /* Bogus initialize for MetroWerks            */
  478.         switch (aeTargetAddressType) {
  479.         case kAETargetSelfCurrentProcess:
  480.             /*
  481.              * Note that, if you use this case, the Apple Event
  482.              * Manager will bypass the event loop and call your
  483.              * handlers directly.
  484.              */
  485.             myPSN.highLongOfPSN = 0;
  486.             myPSN.lowLongOfPSN = kCurrentProcess;
  487.             theTarget = "\pLocal direct linkage"; 
  488.             goto makeDescriptor;
  489.         case kAETargetSelfUsingPSN:
  490.             /*
  491.              * This case always calls through the event loop.
  492.              */
  493.             status = GetCurrentProcess(&myPSN);
  494.             theTarget = "\pLocal linkage through event loop"; 
  495.             if (status == noErr) {
  496. makeDescriptor:    status = AECreateDesc(
  497.                         typeProcessSerialNumber,
  498.                         (Ptr) &myPSN,
  499.                         sizeof (ProcessSerialNumber),
  500.                         theAddress
  501.                     );
  502.             }
  503.             break;
  504.         case kAETargetOtherApplication:
  505.             status = AEBrowseForTarget(
  506.                         NULL, NULL, NULL, NULL, theAddress, theTarget);
  507.             break;
  508.         }
  509.         if (status == noErr && targetName != NULL)
  510.             BlockMoveData(theTarget, targetName, theTarget[0] + 1);
  511.         return (status);
  512. }
  513.  
  514. /*
  515.  * Call the PPC Toolbox browser to locate a target application.
  516.  *    dialogPrompt        -> "Choose a program to link to" if NULL
  517.  *    listHeader            -> "Programs"
  518.  *    theAddress            <- the result
  519.  *    targetName            <- the application name text for error alerts
  520.  */
  521. pascal OSErr
  522. AEBrowseForTarget(
  523.         ConstStr255Param        dialogPrompt,
  524.         ConstStr255Param        listHeader,
  525.         PPCFilterUPP            filterProcUPP,
  526.         ConstStr255Param        locNBPType,                
  527.         AEDesc                    *theAddress,
  528.         StringPtr                targetName
  529.     )
  530. {
  531.         LocationNameRec            theLoc;
  532.         PortInfoRec                theRec;
  533.         OSErr                    status;
  534.         TargetID                theID;
  535.  
  536.         status = PPCBrowser(
  537.                     dialogPrompt,
  538.                     listHeader,
  539.                     FALSE,            /* No default        */
  540.                     &theLoc,
  541.                     &theRec,
  542.                     filterProcUPP,    
  543.                     locNBPType
  544.                 );
  545.         if (status == noErr) {
  546.             /*
  547.              * Create a target descriptor
  548.              */
  549.             BlockMoveData(
  550.                 theRec.name.name,
  551.                 targetName,
  552.                 theRec.name.name[0] + 1
  553.             );
  554.             theID.name = theRec.name;
  555.             theID.location = theLoc;
  556.             status = AECreateDesc(
  557.                         typeTargetID,
  558.                         (Ptr) &theID,
  559.                         sizeof(theID),
  560.                         theAddress
  561.                     );
  562.         }
  563.         if (status == noErr)
  564.             ParamText(targetName, "\p", "\p", "\p");
  565.         return (status);
  566. }
  567.  
  568. /*
  569.  * Call IPCListPorts to locate a target application.
  570.  *    machineName            -> the machine to look for
  571.  *    targetNameVector    -> a vector (NULL terminated) of application name strings.
  572.  *    theAddress            <- the result
  573.  *    targetName            <- the application name text for error alerts
  574.  */
  575. pascal OSErr
  576. AELocateTarget(
  577.         ConstStr255Param        machineName,
  578.         const StringPtr            *targetNameVector,
  579.         AEDesc                    *theAddress,
  580.         StringPtr                actualTargetName
  581.     )
  582. {
  583.         LocationNameRec            locationNameRec;
  584.         OSErr                    status;
  585.         TargetID                theID;
  586.         IPCListPortsPBRec        ipcListPortsPBRec;
  587.         PPCPortRec                ppcPortRec;
  588.         PortInfoRec                portInfoRec;
  589.         short                    i;
  590.         short                    j;
  591. #define IPC        (ipcListPortsPBRec)
  592. #define LOC        (locationNameRec)
  593. #define PORT    (ppcPortRec)
  594. #define INFO    (portInfoRec)
  595.  
  596.         CLEAR(PORT);
  597.         PORT.nameScript = smRoman;
  598.         pstrcpy(PORT.name, "\p=");
  599.         PORT.portKindSelector = ppcByString;
  600.         pstrcpy(PORT.u.portTypeStr, "\p=");
  601.         CLEAR(LOC);
  602.         LOC.locationKindSelector = ppcNBPLocation;
  603.         pstrcpy(LOC.u.nbpEntity.objStr, (void *) machineName);
  604.         pstrcpy(LOC.u.nbpEntity.typeStr, "\pPPCToolBox");
  605.         AEGetMyZone(LOC.u.nbpEntity.zoneStr);
  606.         status = noErr;
  607.         for (i = 0; status == noErr; i++) {
  608.             CLEAR(IPC);
  609.             IPC.startIndex = i;
  610.             IPC.requestCount = 1;
  611.             IPC.portName = &PORT;
  612.             IPC.locationName = &LOC;
  613.             IPC.bufferPtr = &portInfoRec;
  614.             status = IPCListPorts(&IPC, FALSE);
  615.             if (status == noErr) {
  616.                 BlockMoveData(
  617.                     INFO.name.name,
  618.                     actualTargetName,
  619.                     INFO.name.name[0] + 1
  620.                 );
  621.                 for (j = 0; targetNameVector[j] != NULL; j++) {
  622.                     if (EqualString(
  623.                             actualTargetName, targetNameVector[j], FALSE, FALSE)) {
  624.                         theID.name = INFO.name;
  625.                         theID.location = LOC;
  626.                         status = AECreateDesc(
  627.                                 typeTargetID,
  628.                                 (Ptr) &theID,
  629.                                 sizeof(theID),
  630.                                 theAddress
  631.                             );
  632.                         goto exit;
  633.                     }
  634.                 }
  635.             }
  636.         }
  637. exit:    return (status);
  638. #undef IPC
  639. #undef LOC
  640. #undef PORT
  641. #undef INFO
  642. }
  643.  
  644. /*
  645.  * This should be called before doing any user-interaction, such as alerts
  646.  * or dialogs. It returns FALSE if interaction is blocked at this time.
  647.  * The application should provide an idle function UPP. For example,
  648.  *
  649.  *        pascal Boolean
  650.  *        MyAEIdleProc(
  651.  *                const EventRecord        *theEventPtr,
  652.  *                long                    *sleepTime,
  653.  *                RgnHandle                *mouseRgn
  654.  *            )
  655.  *        {
  656.  *                if (theEventPtr->what == kHighLevelEvent)
  657.  *                    return (TRUE);
  658.  *                else {
  659.  *                    *sleepTime = ProcessThisEvent(theEventPtr);
  660.  *                    return (FALSE);
  661.  *                }
  662.  *        }        
  663.  */
  664. pascal Boolean
  665. AEInteractionOK(
  666.         AEIdleUPP                aeIdleUPP
  667.     )
  668. {
  669.         Boolean                    result;
  670.         OSErr                    status;
  671.  
  672.         if (GLOBAL.currentEventIsAppleEvent == FALSE)
  673.             result = TRUE;
  674.         else {
  675.             status = AEInteractWithUser(0, NULL, aeIdleUPP);
  676.             result = (status == noErr);
  677.         }
  678.         return (result);
  679. }
  680.  
  681. /*
  682.  * AEGotRequiredParams fails if not all required parameters have been extracted.
  683.  * Call this after retrieving all required parameters before actually processing
  684.  * the event. This sets gCurrentAEStatus to noErr if it succeeds.
  685.  *
  686.  * If required parameters remain, return errAEParamMissed.
  687.  */
  688. pascal OSErr
  689. AEGotRequiredParams(
  690.         const AppleEvent        *theEvent
  691.     )
  692. {
  693.         DescType                descType;
  694.         Size                    actualSize;
  695.         OSErr                    status;
  696.         
  697.         status = AEGetAttributePtr(
  698.                 theEvent,
  699.                 keyMissedKeywordAttr,
  700.                 typeWildCard,
  701.                 &descType,
  702.                 NULL,
  703.                 0,
  704.                 &actualSize
  705.             );
  706.         if (status == errAEDescNotFound) {
  707.             GLOBAL.currentAEStatus = noErr;
  708.             status = noErr;
  709.         }
  710.         else {
  711.             status = errAEParamMissed;
  712.         }
  713.         return (status);
  714. }
  715.  
  716. /*
  717.  * All apple events call this function initially to store common information.
  718.  */
  719. pascal OSErr
  720. AEHandlerSetup(
  721.         const AppleEvent        *theEvent,
  722.         AppleEvent                *theReply,
  723.         long                    refCon
  724.     )
  725. {
  726.         OSErr                    status;
  727.         DescType                actualType;
  728.         Size                    actualSize;
  729.  
  730.         /*
  731.          * Here's where we add the Frontier "shared script" cancel handler.
  732.          */
  733.         GLOBAL.currentAEEvent = theEvent;
  734.         GLOBAL.currentAEReply = theReply;
  735.         GLOBAL.currentAERefCon = refCon;
  736.         GLOBAL.currentAEStatus = errAEEventNotHandled;
  737.         GLOBAL.currentEventIsAppleEvent = TRUE;
  738.         /*
  739.          * Try to extract the class and type parameters, then switch on the
  740.          * event and process what we can. Note that GLOBAL.currentAEStatus is
  741.          * initializad to an error code: the final caller must set the status to
  742.          * noErr if the event was correctly handled. Normally, this is done
  743.          * by AEGotRequiredParams
  744.          */
  745.         status = AEGetAttributePtr(
  746.                     theEvent,
  747.                     keyEventClassAttr,
  748.                     typeType,
  749.                     &actualType,
  750.                     (Ptr) &GLOBAL.currentAEEventClass,
  751.                     sizeof GLOBAL.currentAEEventClass,
  752.                     &actualSize
  753.                 );
  754.         if (status == noErr) {
  755.             status = AEGetAttributePtr(
  756.                         theEvent,
  757.                         keyEventIDAttr,
  758.                         typeType,
  759.                         &actualType,
  760.                         (Ptr) &GLOBAL.currentAEEventID,
  761.                         sizeof GLOBAL.currentAEEventID,
  762.                         &actualSize
  763.                     );
  764.         }
  765.         if (status == noErr) {
  766.             status = AEGetAttributePtr(
  767.                     theEvent,
  768.                     keyInteractLevelAttr,
  769.                     typeInteger,
  770.                     &actualType,
  771.                     (Ptr) &GLOBAL.currentAEIntractionLevel,
  772.                     sizeof GLOBAL.currentAEIntractionLevel,
  773.                     &actualSize
  774.             );
  775.         }
  776.         return (status);
  777. }
  778.  
  779. /*
  780.  * These functions get and set data in the AppleEvent. They are only needed
  781.  * if we intend to receive events.
  782.  */
  783.  
  784. /*
  785.  * AEGetShort extracts a signed short integer from the parameter list.
  786.  * Return noErr on success, errAEDescNotFound if the parameter was missing.
  787.  */
  788. pascal OSErr
  789. AEGetShort(
  790.         const AppleEvent        *theEvent,
  791.         DescType                parameterKey,
  792.         short                    *result
  793.     )
  794. {
  795.         OSErr                    status;
  796.         Size                    actualSize;
  797.         DescType                actualType;
  798.  
  799.         status = AEGetParamPtr(
  800.                     theEvent,
  801.                     parameterKey,
  802.                     typeSMInt,
  803.                     &actualType,
  804.                     (Ptr) result,
  805.                     sizeof (short),
  806.                     &actualSize
  807.                 );
  808.         return (status);
  809. }
  810.  
  811. /*
  812.  * AEGetLong extracts an signed short integer from the parameter list.
  813.  */
  814. pascal OSErr
  815. AEGetLong(
  816.         const AppleEvent        *theEvent,
  817.         DescType                parameterKey,
  818.         long                    *result
  819.     )
  820. {
  821.         OSErr                    status;
  822.         Size                    actualSize;
  823.         DescType                actualType;
  824.  
  825.         status = AEGetParamPtr(
  826.                     theEvent,
  827.                     parameterKey,
  828.                     typeInteger,
  829.                     &actualType,
  830.                     (Ptr) result,
  831.                     sizeof (long),
  832.                     &actualSize
  833.                 );
  834.         return (status);
  835. }
  836.  
  837. /*
  838.  * AEGetBoolean extracts a Boolean from the parameter list.
  839.  */
  840. pascal OSErr
  841. AEGetBoolean(
  842.         const AppleEvent        *theEvent,
  843.         DescType                parameterKey,
  844.         Boolean                    *result
  845.     )
  846. {
  847.         OSErr                    status;
  848.         Size                    actualSize;
  849.         DescType                actualType;
  850.         
  851.         status = AEGetParamPtr(
  852.                     theEvent,
  853.                     parameterKey,
  854.                     typeBoolean,
  855.                     &actualType,
  856.                     (Ptr) result,
  857.                     sizeof (Boolean),
  858.                     &actualSize
  859.                 );
  860.         return (status);
  861. }
  862.  
  863. /*
  864.  * GetAEChars extracts a text item from the parameter list, returning it in a
  865.  * newly-allocated CharsHandle. The caller must dispose the handle.
  866.  */
  867. pascal OSErr
  868. AEGetChars(
  869.         const AppleEvent        *theEvent,
  870.         DescType                parameterKey,
  871.         CharsHandle                *result
  872.     )
  873. {
  874.         OSErr                    status;
  875.         AEDesc                    theDesc;
  876.  
  877.         status = AEGetParamDesc(
  878.                         theEvent,
  879.                         parameterKey,
  880.                         typeChar,
  881.                         &theDesc
  882.                     );
  883.         if (status == noErr)
  884.             *result = (CharsHandle) theDesc.dataHandle;
  885.         return (status);
  886. }
  887.  
  888. /*
  889.  * GetAEString extracts a Str255 from the parameter list.
  890.  */
  891. pascal OSErr
  892. AEGetString(
  893.         const AppleEvent        *theEvent,
  894.         DescType                parameterKey,
  895.         StringPtr                result
  896.     )
  897. {
  898.         OSErr                    status;
  899.         Size                    actualSize;
  900.         DescType                actualType;
  901.  
  902.         status = AEGetParamPtr(
  903.                     theEvent,
  904.                     parameterKey,
  905.                     typeChar,
  906.                     &actualType,
  907.                     (Ptr) &result[1],
  908.                     sizeof (Str255) - 1,
  909.                     &actualSize
  910.                 );
  911.         result[0] = actualSize;
  912.         return (status);
  913. }
  914.  
  915. /*
  916.  * AEPutShort stores a short integer into an AppleEvent reply.
  917.  */
  918. pascal OSErr
  919. AEPutShort(
  920.         AppleEvent                *theReply,
  921.         DescType                parameterKey,
  922.         short                    value
  923.     )
  924. {
  925.         OSErr                    status;
  926.         
  927.         status = AEPutParamPtr(
  928.                     theReply,
  929.                     parameterKey,
  930.                     typeSMInt,
  931.                     (Ptr) &value,
  932.                     sizeof value
  933.                 );
  934.         return (status);
  935. }
  936.  
  937. /*
  938.  * AEPutBoolean stores a Boolean into the AppleEvent reply.
  939.  */
  940. pascal OSErr
  941. AEPutBoolean(
  942.         AppleEvent                *theReply,
  943.         DescType                parameterKey,
  944.         Boolean                    value
  945.     )
  946. {
  947.         OSErr                    status;
  948.         
  949.         status = AEPutParamPtr(
  950.                     theReply,
  951.                     parameterKey,
  952.                     typeBoolean,
  953.                     (Ptr) &value,
  954.                     sizeof value
  955.                 );
  956.         return (status);
  957. }
  958.  
  959. /*
  960.  * AEPutLong stores a long integer into the AppleEvent reply.
  961.  */
  962. pascal OSErr
  963. AEPutLong(
  964.         AppleEvent                *theReply,
  965.         DescType                parameterKey,
  966.         long                    value
  967.     )
  968. {
  969.         OSErr                    status;
  970.         
  971.         status = AEPutParamPtr(
  972.                     theReply,
  973.                     parameterKey,
  974.                     typeInteger,
  975.                     (Ptr) &value,
  976.                     sizeof value
  977.                 );
  978.         return (status);
  979. }
  980.  
  981. /*
  982.  * AEPutStringHandle stores a StringHandle into the AppleEvent reply.
  983.  */
  984. pascal OSErr
  985. AEPutStringHandle(
  986.         AppleEvent                *theReply,
  987.         DescType                parameterKey,
  988.         const StringHandle        value
  989.     )
  990. {
  991.         OSErr                    status;
  992.         short                    lockState;
  993.         
  994.         lockState = HGetState((Handle) value);
  995.         HLock((Handle) value);
  996.         status = AEPutString(theReply, parameterKey, *value);
  997.         HSetState((Handle) value, lockState);
  998.         return (status);
  999. }
  1000.  
  1001. /*
  1002.  * AEPutCharsHandle stores a CharsHandle into the AppleEvent reply.
  1003.  */
  1004. pascal OSErr
  1005. AEPutCharsHandle(
  1006.         AppleEvent                *theReply,
  1007.         DescType                parameterKey,
  1008.         const CharsHandle        value
  1009.     )
  1010. {
  1011.         OSErr                    status;
  1012.         short                    lockState;
  1013.         
  1014.         lockState = HGetState((Handle) value);
  1015.         HLock((Handle) value);
  1016.         status = AEPutParamPtr(
  1017.                     theReply,
  1018.                     parameterKey,
  1019.                     typeChar,
  1020.                     (Ptr) *value,
  1021.                     GetHandleSize((Handle) value)
  1022.                 );
  1023.         HSetState((Handle) value, lockState);
  1024.         return (status);
  1025. }
  1026.  
  1027.  
  1028. /*
  1029.  * AEPutString stores a Str255 into the AppleEvent reply.
  1030.  */
  1031. pascal OSErr
  1032. AEPutString(
  1033.         AppleEvent                *theReply,
  1034.         DescType                parameterKey,
  1035.         ConstStr255Param        value
  1036.     )
  1037. {
  1038.         OSErr                    status;
  1039.         
  1040.         status = AEPutParamPtr(
  1041.                     theReply,
  1042.                     parameterKey,
  1043.                     typeChar,
  1044.                     (Ptr) &value[1],
  1045.                     value[0]
  1046.                 );
  1047.         return (status);
  1048. }
  1049.  
  1050. /*
  1051.  * Local function for AELocateTarget
  1052.  */
  1053. static void
  1054. AEGetMyZone(
  1055.         Str32                    zoneName
  1056.     )
  1057. {
  1058.         XPPParamBlock            pb;
  1059.         OSErr                    status;
  1060. #define PB    (pb)
  1061. #define kXPPTimeout                3
  1062. #define kXPPRetry                4
  1063.  
  1064.         CLEAR(PB);
  1065.         PB.XCALL.xppTimeout = kXPPTimeout;
  1066.         PB.XCALL.xppRetry = kXPPRetry;
  1067.         PB.XCALL.zipBuffPtr = (Ptr) zoneName;
  1068.         PB.XCALL.zipInfoField[0] = 0;
  1069.         PB.XCALL.zipInfoField[1] = 0;
  1070.         status = GetMyZone(&PB, FALSE);
  1071.         if (status == noBridgeErr) {
  1072.             zoneName[0] = 1;
  1073.             zoneName[1] = '*';
  1074.         }
  1075.         else if (status != noErr) {
  1076.             zoneName[0] = 0;
  1077.         }
  1078. #undef PB
  1079. }
  1080.  
  1081. static void
  1082. ClearMemory(
  1083.         void                    *dataPtr,
  1084.         register long            size
  1085.     )
  1086. {
  1087.         register char            *ptr;
  1088.  
  1089.         ptr = (char *) dataPtr;
  1090.         while (size > 0) {
  1091.             *ptr++ = 0;
  1092.             --size;
  1093.         }
  1094. }
  1095.  
  1096. static void
  1097. pstrcpy(
  1098.         StringPtr                dst,
  1099.         ConstStr255Param        src
  1100.     )
  1101. {
  1102.         BlockMoveData(src, dst, src[0] + 1);
  1103. }
  1104.  
  1105. static void
  1106. pstrcat(
  1107.         StringPtr                dst,
  1108.         ConstStr255Param        src
  1109.     )
  1110. {
  1111.         short                    length;
  1112.         
  1113.         length = 255 - dst[0];
  1114.         if (length > src[0])
  1115.             length = src[0];
  1116.         BlockMoveData(&src[1], &dst[1] + dst[0], length);
  1117.         dst[0] += length;
  1118. }
  1119.  
  1120.